
package com.kun.handler.access;

import org.springframework.core.convert.converter.Converter;
import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * 返回前端格式化数据
 *
 * @author kun.li
 */
public final class DefaultOAuth2AccessTokenResponseMapConverter implements Converter<OAuth2AccessTokenResponse, Map<String, Object>> {

    @Override
    public Map<String, Object> convert(OAuth2AccessTokenResponse tokenResponse) {
        Map<String, Object> responseResult = new HashMap<>();
        responseResult.put("code", 200);
        responseResult.put("state", true);
        responseResult.put("message", "认证成功");
        Map<String, Object> parameters = new HashMap<>();
        parameters.put("accessToken", tokenResponse.getAccessToken().getTokenValue());
        parameters.put("tokenType", tokenResponse.getAccessToken().getTokenType().getValue());
        parameters.put("expiresIn", getExpiresIn(tokenResponse));
        parameters.put("expireAt", Objects.requireNonNull(tokenResponse.getAccessToken().getExpiresAt()).toEpochMilli());
        if (!CollectionUtils.isEmpty(tokenResponse.getAccessToken().getScopes())) {
            parameters.put(OAuth2ParameterNames.SCOPE,
                    StringUtils.collectionToDelimitedString(tokenResponse.getAccessToken().getScopes(), " "));
        }
        if (tokenResponse.getRefreshToken() != null) {
            parameters.put("refreshToken", tokenResponse.getRefreshToken().getTokenValue());
        }
        if (!CollectionUtils.isEmpty(tokenResponse.getAdditionalParameters())) {
            for (Map.Entry<String, Object> entry : tokenResponse.getAdditionalParameters().entrySet()) {
                parameters.put(entry.getKey(), entry.getValue());
            }
        }
        responseResult.put("data", parameters);
        return responseResult;
    }

    private static long getExpiresIn(OAuth2AccessTokenResponse tokenResponse) {
        if (tokenResponse.getAccessToken().getExpiresAt() != null) {
            return ChronoUnit.SECONDS.between(Instant.now(), tokenResponse.getAccessToken().getExpiresAt());
        }
        return -1;
    }

}
